package plugincontext

import (
	"context"
	"errors"
	"fmt"
	"gitee.com/go-caipu-team/go-caipu-plugin-sdk/pkg/utils"
	"github.com/goccy/go-json"
	"go-caipu/pkg/setting"
	"gorm.io/gorm"
	"math/rand"
	"time"

	"gitee.com/go-caipu-team/go-caipu-plugin-sdk/backend"
	"go-caipu/pkg/infra/localcache"
	"go-caipu/pkg/infra/log"
	"go-caipu/pkg/plugins"
	datasource "go-caipu/pkg/services/datasources"
)

type Provider struct {
	cfg               *setting.Cfg
	cacheService      *localcache.CacheService
	pluginStore       plugins.Store
	dataSourceService datasource.Service
	logger            log.Logger
}

func ProvidePluginContextProvider(setting *setting.Cfg, cacheService *localcache.CacheService, pluginStore plugins.Store, dataSourceService datasource.Service) *Provider {
	return &Provider{
		cfg:               setting,
		cacheService:      cacheService,
		pluginStore:       pluginStore,
		dataSourceService: dataSourceService,
		logger:            log.New("plugincontext"),
	}
}
func (p *Provider) Get(ctx context.Context, pluginID string) (backend.PluginContext, bool, error) {
	return p.pluginContext(ctx, pluginID)
}
func (p *Provider) pluginContext(ctx context.Context, pluginID string) (backend.PluginContext, bool, error) {

	pdto, exists := p.pluginStore.Plugin(ctx, pluginID)
	if !exists {
		return backend.PluginContext{}, false, errors.New("plugin not found")
	}
	//没有数据源插件填充默认信息
	if pdto.Type != plugins.DataSource && pdto.Type != plugins.App {
		return backend.PluginContext{
			PluginID: pluginID,
			AppInstanceSettings: &backend.AppInstanceSettings{
				JSONData:                []byte("{}"),
				DecryptedSecureJSONData: map[string]string{},
			},
			DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
				JSONData:                []byte("{}"),
				DecryptedSecureJSONData: map[string]string{},
			},
		}, true, nil
	}

	//jsonData := json.RawMessage{}
	decryptedSecureJSONData := map[string]string{}
	var updated time.Time
	//缓存加载
	cacheKey := getCacheKey(pluginID)
	if cached, found := p.cacheService.Get(cacheKey); found {
		return cached.(backend.PluginContext), true, nil
	}
	//数据库加载
	ds, err := p.dataSourceService.GetDataSourceByType(ctx, pluginID)
	if err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			return backend.PluginContext{}, false, fmt.Errorf("%v: %w", "Failed to get plugin datasource", err)
		}
	}
	updated = ds.UpdatedAt

	//解密字段
	err = json.Unmarshal([]byte(ds.SecureJsonData), &decryptedSecureJSONData)
	if err != nil {
		return backend.PluginContext{}, false, fmt.Errorf("%v: %w", "Failed to Marshal plugin SecureJsonData ", err)
	}
	encrypt := utils.New(p.cfg.Application.EncryptionKey)
	for key, value := range decryptedSecureJSONData {
		decryptedSecureJSONData[key], _ = encrypt.Decrypt(value) //前端解密，再用加密算法加密
	}

	//accessToken:随机生成GRPServer token 用于插件回调使用
	//plugin-id: 用于验证来源和插件回调token匹配
	decryptedSecureJSONData[backend.GRPCTokenKey] = randomString(20)
	decryptedSecureJSONData[backend.GRPCPluginKey] = pluginID

	ptx := backend.PluginContext{
		PluginID: ds.Type,
		AppInstanceSettings: &backend.AppInstanceSettings{
			JSONData:                ds.JsonData,
			DecryptedSecureJSONData: decryptedSecureJSONData,
			Updated:                 updated,
		},
		DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{
			ID:                      ds.Id,
			Name:                    ds.Name,
			JSONData:                ds.JsonData,
			DecryptedSecureJSONData: decryptedSecureJSONData,
			Updated:                 updated,
		},
	}
	p.cacheService.Cache.Set(cacheKey, ptx, pluginSettingsCacheTTL)
	return ptx, true, nil
}
func randomString(length int) string {
	//rand.New(rand.NewSource(time.Now().UnixNano()))
	chars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	result := ""
	for i := 0; i < length; i++ {
		result += string(chars[rand.Intn(len(chars))])
	}
	return result
}

const pluginSettingsCacheTTL = 5 * time.Second
const pluginSettingsCachePrefix = "plugin-setting-"

func getCacheKey(pluginID string) string {
	return pluginSettingsCachePrefix + pluginID
}
